package com.webservice;

import com.carpark.ejb.DAO.DAO;
import com.carpark.ejb.DAO.DaoImpl;
import com.carpark.ejb.Model.ClientsModel;
import java.io.IOException;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

/**
 *
 * @author Sawior
 */
@ManagedBean
@SessionScoped
public class LoginBean implements Serializable {

    private static final long serialVersionUID = 7765876811740798583L;
    private String username;
    private String password;
    private int id = -1;
    private boolean loggedIn;
    public static boolean admin = false;
    @ManagedProperty(value = "#{navigationBean}")
    private NavigationBean navigationBean;
    private final DAO dao = getSingleDao();
    DaoSingleObject dso;

    public String doLogin() {
        ClientsModel client = findClientInDataBase(username);
        if (username.equals("admin") && password.equals("carpark123")) {
            admin = true;
            return loginSuccess();
        }

        if (client == null) {
            return loginFailed();
        } else {
            if (checkClientPassword(password, client.getPassword())) {
                if (!checkIsBlocked(client)) {
                    id = client.getClientId();
                    return loginSuccess();
                }
                return userBlocked();
            } else {
                return loginFailed();
            }
        }
    }

    public String forgotPassword() {
        return navigationBean.forgotPassword();
    }

    public DAO getSingleDao() {
        if (this.dso == null) {
            FacesContext context = FacesContext.getCurrentInstance();
            Application app = context.getApplication();
            this.dso = (DaoSingleObject) app.evaluateExpressionGet(context, "#{daoSingleObject}", DaoSingleObject.class);
        }
        return this.dso.dao;
    }

    private boolean checkClientPassword(String actualPassword, String realPassword) {
        try {
            return realPassword.equals(codePassword(actualPassword));
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE, "[CarPark] No password security algorithm found.", ex);
        }
        return false;
    }

    private String codePassword(String password) throws NoSuchAlgorithmException {
        MessageDigest md;
        md = MessageDigest.getInstance("MD5");
        md.update(password.getBytes());
        byte byteData[] = md.digest();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < byteData.length; i++) {
            sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
        }

        return sb.toString();
    }

    private ClientsModel findClientInDataBase(String email) {
        return dao.getClientByEmail(email);
    }

    private String loginFailed() {
        FacesMessage msg = new FacesMessage();
        msg.setSeverity(FacesMessage.SEVERITY_ERROR);
        msg.setDetail("Zły użytkownik lub hasło");
        msg.setSummary("Zły użytkownik lub hasło");
        FacesContext.getCurrentInstance().addMessage(null, msg);
        Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE, "[CarPark] UserLogin failed. Wrong password, username.");

        return navigationBean.toLogin();
    }

    private String userBlocked() {
        FacesMessage msg = new FacesMessage();
        msg.setSeverity(FacesMessage.SEVERITY_ERROR);
        msg.setDetail("Twoje konto zostało zablokowane");
        msg.setSummary("Użytkownik zablokowany");
        FacesContext.getCurrentInstance().addMessage(null, msg);
        Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE, "[CarPark] UserLogin failed. User has been blocked.");

        return navigationBean.toLogin();
    }

    private boolean checkIsBlocked(ClientsModel client) {
        if (client.getBlocked() == null) {
            return false;
        }
        return client.getBlocked();
    }

    private String loginSuccess() {
        loggedIn = true;
        FacesMessage msg = new FacesMessage();
        msg.setSeverity(FacesMessage.SEVERITY_INFO);
        msg.setSummary("Zalogowano pomyślnie");
        FacesContext.getCurrentInstance().addMessage(null, msg);
        Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE, "[CarPark] User login success.");
        return navigationBean.redirectToWelcome();
    }

    public String doLogout() throws IOException {
        loggedIn = false;
        id = -1;
        FacesMessage msg = new FacesMessage();
        msg.setSeverity(FacesMessage.SEVERITY_INFO);
        msg.setSummary("Wylogowano.");
        Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE, "[CarPark] User logout success.");
        FacesContext.getCurrentInstance().addMessage(null, msg);
        ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
        ec.invalidateSession();
        ec.redirect(ec.getRequestContextPath() + "/index.xhtml");
        admin = false;
        return navigationBean.toLogin();
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public boolean isLoggedIn() {
        return loggedIn;
    }

    public boolean isLoggedInAdmin() {
        return loggedIn && admin;
    }

    public void setLoggedIn(boolean loggedIn) {
        this.loggedIn = loggedIn;
    }

    public void setNavigationBean(NavigationBean navigationBean) {
        this.navigationBean = navigationBean;
    }

    public int getId() {
        return id;
    }
}
